#pragma once

#include <map>
#include <string>
#include <vector>

struct lua_State;

class LuaTable
{
	friend class LuaFile;

	public:
		LuaTable();
		LuaTable(const LuaTable& table);
		LuaTable& operator=(const LuaTable& table);
		~LuaTable();

		bool IsValid() const { return (m_LuaFile != NULL); }

		int GetLength() const;					// Lua # operator
		int GetLength(int key) const;			// Lua # operator
		int GetLength(const std::string& key) const;	// Lua # operator

		bool GetKeys(std::vector<int>& data) const;
		bool GetKeys(std::vector<std::string>& data) const;

		bool GetMap(std::map<int, float>& data) const;
		bool GetMap(std::map<int, std::string>& data) const;
		bool GetMap(std::map<std::string, float>& data) const;
		bool GetMap(std::map<std::string, std::string>& data) const;

		bool KeyExists(int key) const;
		bool KeyExists(const std::string& key) const;

		int  GetType(int key) const;
		int  GetType(const std::string& key) const;

		// Numeric Keys
		int		GetInt(int key, int def) const;
		bool	GetBool(int key, bool def) const;
		float	GetFloat(int key, float def) const;
		std::string	GetString(int key, const std::string& def) const;

		// String Keys
		int		GetInt(const std::string& key, int def) const;
		bool	GetBool(const std::string& key, bool def) const;
		float	GetFloat(const std::string& key, float def) const;
		std::string	GetString(const std::string& key, const std::string& def) const;

		LuaTable SubTable(int key) const;
		LuaTable SubTable(const std::string& key) const;
		LuaTable SubTableExpr(const std::string& expr) const;

	private:
		LuaTable(LuaFile* lfile);

		bool PushTable() const;
		bool PushValue(int key) const;
		bool PushValue(const std::string& key) const;

	private:
		lua_State* L;
		int m_RefNum;

		LuaFile* m_LuaFile;
		mutable bool m_bIsValid;

		std::string m_szPath;
};